package com.example.audio_test.utils

import android.media.*
import java.io.File
import java.io.FileInputStream
import java.io.IOException
import java.lang.Exception

/**
 *音频解码播放线程
 *
 * @author : Kun
 * @date : 2021/6/24
 * @time : 10:33
 */
class AudioMediaCodecWorker(private val filePath: String) : Thread() {

    private var mediaExtractor: MediaExtractor = MediaExtractor()
    private var mediaCodec: MediaCodec? = null

    private var isStop = false

    override fun run() {
        try {

//            mediaExtractor.setDataSource(filePath)
            val inputSystem = FileInputStream(File(filePath))
            mediaExtractor.setDataSource(inputSystem.fd)
        } catch (e: IOException) {
            e.printStackTrace()
        }
        var audioTrack: AudioTrack? = null

        //筛选音轨
        for (i in 0 until mediaExtractor.trackCount) {
            val mediaFormat = mediaExtractor.getTrackFormat(i)
            val mine = mediaFormat.getString(MediaFormat.KEY_MIME)
            if (mine!!.startsWith("audio/")) {
                mediaExtractor.selectTrack(i)
                try {
                    mediaCodec = MediaCodec.createDecoderByType(mine)
                } catch (e: IOException) {
                    e.printStackTrace()
                }
                mediaCodec!!.configure(mediaFormat, null, null, 0)

                //声道数
                val audioChannels = mediaFormat.getInteger(MediaFormat.KEY_CHANNEL_COUNT)
                //采样率
                val mSampleRate = mediaFormat.getInteger(MediaFormat.KEY_SAMPLE_RATE)

                audioTrack = AudioTrack(
                    AudioAttributes.Builder().setLegacyStreamType(AudioManager.STREAM_MUSIC)
                        .build(),
                    AudioFormat.Builder()
                        .setChannelMask(if (audioChannels == 1) AudioFormat.CHANNEL_OUT_MONO else AudioFormat.CHANNEL_OUT_STEREO)
                        .setEncoding(AudioFormat.ENCODING_PCM_16BIT)
                        .setSampleRate(mSampleRate)
                        .build(),
                    AudioRecord.getMinBufferSize(
                        mSampleRate,
                        if (audioChannels == 1) AudioFormat.CHANNEL_OUT_MONO else AudioFormat.CHANNEL_OUT_STEREO,
                        AudioFormat.ENCODING_PCM_16BIT
                    ),
                    AudioTrack.MODE_STREAM,
                    AudioManager.AUDIO_SESSION_ID_GENERATE
                )
            }
        }

        //未获取到音轨，返回
        mediaCodec?.start() ?: return
        audioTrack?.play()

        /**
         * 是否已经结束
         */
        var isEnd = false

        loop@ while (!isStop) {
            if (!isEnd) {
                try {
                    val inputIndex = mediaCodec!!.dequeueInputBuffer(0)
                    if (inputIndex > 0) {
                        val buffer = mediaCodec!!.getInputBuffer(inputIndex) ?: continue
                        val sampleSize = mediaExtractor.readSampleData(buffer, 0)

                        if (sampleSize < 0) {
                            //读取完成了
                            mediaCodec!!.queueInputBuffer(
                                inputIndex,
                                0,
                                0,
                                0,
                                MediaCodec.BUFFER_FLAG_END_OF_STREAM
                            )
                            isEnd = true
                        } else {
                            mediaCodec!!.queueInputBuffer(
                                inputIndex,
                                0,
                                sampleSize,
                                mediaExtractor.sampleTime,
                                0
                            )
                            mediaExtractor.advance()
                        }
                    }
                } catch (e: Exception) {
                    e.printStackTrace()
                }
            }

            try {
                val bufferInfo = MediaCodec.BufferInfo()
                when (val outputIndex = mediaCodec!!.dequeueOutputBuffer(bufferInfo, 0)) {
                    // 此类型已经废弃，如果使用的是getOutputBuffer（）可以忽略此状态
                    MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED -> {
                        // 当buffer的格式发生改变，须指向新的buffer格式
                    }
                    MediaCodec.INFO_OUTPUT_FORMAT_CHANGED -> {
                        // 当buffer的格式发生改变，须指向新的buffer格式
                    }
                    MediaCodec.INFO_TRY_AGAIN_LATER -> {
                        //超时
                    }
                    else -> {
                        val buffer = mediaCodec!!.getOutputBuffer(outputIndex) ?: continue@loop
                        buffer.position(0)
                        //读取数据
                        val outData = ByteArray(bufferInfo.size)
                        buffer.get(outData)
                        //清空缓存
                        buffer.clear()

                        audioTrack!!.write(outData, 0, outData.size)

                        mediaCodec!!.releaseOutputBuffer(outputIndex, true)
                    }
                }
                //播放结束
                if ((bufferInfo.flags and MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
                    break
                }

            } catch (e: Exception) {
                e.printStackTrace()
            }
        }

        try {
            mediaCodec!!.stop()
            mediaCodec!!.release()
            mediaExtractor.release()
            audioTrack!!.stop()
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    fun stopPlay() {
        isStop = false
    }
}